/**
  ******************************************************************************
  * @file   ADCx.c  
  * @brief  ADC驱动初始化  
  * @author Moon
  * @version V1.0.0
  * @date 2022/01/10
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
#include "drv_f4_ocadc.h"
#include "FreeRTOS.h"
#include "task.h"
/* Private defines -----------------------------------------------------------*/

#define USE_ADC_NUM		   			3
#define SAMPLING_MAX_SIZE          	200      //10kHz采样

/* Private Struct  -----------------------------------------------------------*/
typedef struct
{
	uint16_t 			addr;
	uint16_t 			length;
	uint8_t 			MCT;	   					//双缓冲地址
	int16_t 			AR0[SAMPLING_MAX_SIZE];
	int16_t 			AR1[SAMPLING_MAX_SIZE];
} ADCDMAParDef_t;

typedef struct 
{
	DMA_Stream_TypeDef	*dma_type;							//DMA地址
	uint32_t			ADC_DMA_channel;					//DMA通道
	uint32_t			ADC_DMA_IT_type;					//DMA中断类型
	uint32_t			ADC_DMA_IT_ALL;						//DMA中断所有类型
	void				(*callback)(int16_t *, uint16_t);	//数据返回回调
	ADCDMAParDef_t		ADC_DMA_par;						//数据
} ADCx_DMA_t;

typedef struct 
{
	ADC_TypeDef			*ADC_type;					//ADC类型
	uint8_t				channel;					//ADC通道
	GPIO_TypeDef 		*ADC_GPIOx;					//GPIO类型
	uint32_t 			ADC_pin;					//pin值

	uint8_t				sample;						//采样周期
	uint32_t			TrigConvEdge;				//触发类型
	uint32_t			TrigConv;					//触发选择

	ADCx_DMA_t			*ADCx_dma;					//DMA信息地址
} ADCx_t;

typedef struct 
{
	ADC_TypeDef			*type;						//ADC通道
	ADCx_t				*p_ADCx;
} ADC_info_t;

/* Private enum    -----------------------------------------------------------*/


/* Private Variable  ---------------------------------------------------------*/
//Pointer

//Array

static ADCx_DMA_t ADCx_DMA[DMA_ADC_NUM] = 
{
	[DMA_ADC_MF_MONITOR] = {DMA2_Stream0, DMA_Channel_2, DMA_IT_TC, 
	(DMA_FLAG_TCIF0 | DMA_FLAG_TEIF0 | DMA_FLAG_DMEIF0 | DMA_FLAG_FEIF0),
	NULL,}
};

static ADCx_t ADCx[ADC_NUM] = 
{
	[ADC_MCU_TEMP] = {ADC1, ADC_Channel_TempSensor, NULL, 0,
	 ADC_SampleTime_480Cycles, ADC_ExternalTrigConvEdge_None, 0, NULL},
};

static ADC_info_t ADCx_init[USE_ADC_NUM] = 
{
	{ADC1, &ADCx[ADC_MCU_TEMP]},
};
//Const

/* Private function prototypes -----------------------------------------------*/
static void  Adc_Dma_Init(ADC_TypeDef *type, ADCx_DMA_t *adc_dma);
static void ADC_Sampling_Data(ADC_DMA_DEVICE_E index);

/***********************************************************************************
 * @brief Adc_Init 初始化ADC
 * ex:
 * @par
 * None
 * @par Called functions:
 * None
 * @retval
 * @note 默认仅开启通道1
 **********************************************************************************/
void  Adc_Init(void)
{
	uint8_t i, j;

	ADC_InitTypeDef 		ADC_InitStructure;
	GPIO_InitTypeDef 		GPIO_InitStructure;
	ADC_CommonInitTypeDef 	ADC_CommonInitStructure;
	

	for (i = 0; i < ADC_NUM; i++)
	{
		if (ADCx[i].ADC_GPIOx == NULL)
			continue;
		GPIO_InitStructure.GPIO_Pin = ADCx[i].ADC_pin;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
		GPIO_Init(ADCx[i].ADC_GPIOx, &GPIO_InitStructure);
	}

	ADC_TempSensorVrefintCmd(ENABLE);                                          			/* 使能内部温度传感器 */
	ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;                   			/* 独立模式 */
	ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;		/* 两个采样阶段之间的延迟5个时钟 */
	ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;    			/* DMA失能 */
	ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;                			/* 预分频4分频。ADCCLK=PCLK2/4=84/4=21Mhz,ADC时钟最好不要超过36Mhz  */
	ADC_CommonInit(&ADC_CommonInitStructure);                                  			/* 初始化 */

	for (i = 0; i < USE_ADC_NUM; i++)
	{
		ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;						    /* 12位模式 */
		ADC_InitStructure.ADC_ScanConvMode = DISABLE;								    /* 非扫描模式 */
		ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;							    /* 连续转换 */
		ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;						    /* 右对齐 */
		ADC_InitStructure.ADC_NbrOfConversion = 1;									    /* 1个转换在规则序列中 也就是只转换规则序列1  */
		ADC_InitStructure.ADC_ExternalTrigConvEdge = ADCx_init[i].p_ADCx->TrigConvEdge; /* 触发类型选择*/
		ADC_InitStructure.ADC_ExternalTrigConv = ADCx_init[i].p_ADCx->TrigConv;		    /* 触发方式选择*/
		
		ADC_Init(ADCx_init[i].type, &ADC_InitStructure);								/* ADC初始化 */

		if (ADCx_init[i].p_ADCx->ADCx_dma != NULL)
			Adc_Dma_Init(ADCx_init[i].type, ADCx_init[i].p_ADCx->ADCx_dma);

		for (j = 0; j < ADC_NUM; j++)
		{
			if (ADCx[j].ADC_type == ADCx_init[i].type)
			{
				ADC_RegularChannelConfig(ADCx[j].ADC_type, ADCx[j].channel, 1, ADCx[j].sample);
			}
		}

		if (ADCx_init[i].p_ADCx->ADCx_dma != NULL)
		{
			ADC_DMARequestAfterLastTransferCmd(ADCx_init[i].type, ENABLE);
			ADC_DMACmd(ADCx_init[i].type, ENABLE);			
		}
		ADC_Cmd(ADCx_init[i].type, ENABLE);												/* 开启AD转换器 */
	}                                                   
}

/***********************************************************************************
 * @brief Adc_Init 初始化ADC
 * ex:
 * @par
 * None
 * @retval
 **********************************************************************************/
static void  Adc_Dma_Init(ADC_TypeDef *type, ADCx_DMA_t *adc_dma)
{
	DMA_InitTypeDef  DMA_InitStructure;

	DMA_DeInit(adc_dma->dma_type);
	while (DMA_GetCmdStatus(adc_dma->dma_type) != DISABLE){}

	/* 配置 DMA Stream */
	DMA_InitStructure.DMA_Channel = adc_dma->ADC_DMA_channel;
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&type->DR;                	  	/* DMA外设地址 */
	DMA_InitStructure.DMA_Memory0BaseAddr = (u32)adc_dma->ADC_DMA_par.AR0;  /* DMA 存储器0地址 */
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;                       	/* 外设模式到存储器 */
	DMA_InitStructure.DMA_BufferSize = SAMPLING_MAX_SIZE;                         	/* 数据传输量  */
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;              	/* 外设非增量模式 */
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                       	/* 存储器增量模式 */
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;   	/* 外设数据长度:16位 */
	DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;       	/* 存储器数据长度:16位 */
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                 	/* 使用普通模式  */
	DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;                       	/* 高等优先级 */
	DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
	DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
	DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;                   	/* 存储器突发单次传输 */
	DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;           	/* 外设突发单次传输 */
	DMA_Init(adc_dma->dma_type, &DMA_InitStructure);

	DMA_DoubleBufferModeConfig(adc_dma->dma_type,(u32)adc_dma->ADC_DMA_par.AR1,DMA_Memory_0);
	DMA_DoubleBufferModeCmd(adc_dma->dma_type,ENABLE);

	adc_dma->ADC_DMA_par.MCT = DMA_GetCurrentMemoryTarget(adc_dma->dma_type);

	DMA_ClearFlag(adc_dma->dma_type,adc_dma->ADC_DMA_IT_ALL);   //清除DMA发送完成标志
	DMA_ITConfig(adc_dma->dma_type, adc_dma->ADC_DMA_IT_type,ENABLE);   //触发中断
	DMA_Cmd(adc_dma->dma_type, ENABLE);                  // 开启DMA传输
}

/***********************************************************************************
 * @brief 获取ADC值
 * ex:
 * @par  ch:通道值 0~16
 * None
 * @par Called functions:
 * None
 * @retval 转换结果
 **********************************************************************************/
unsigned short Get_Adc(ADC_DEVICE_E ch)
{
	if (ch >= ADC_NUM)
		return 0;

	//设置指定ADC的规则组通道，一个序列，采样时间
	ADC_RegularChannelConfig(ADCx[ch].ADC_type, ADCx[ch].channel, 1, ADCx[ch].sample);    		/* ADC1,ADC通道,480个周期,提高采样时间可以提高精确度                */
	ADC_SoftwareStartConv(ADCx[ch].ADC_type);                                           		/* 使能指定的ADC1的软件转换启动功能     */
	while(!ADC_GetFlagStatus(ADCx[ch].ADC_type, ADC_FLAG_EOC));                        			/* 等待转换结束 */
	return ADC_GetConversionValue(ADCx[ch].ADC_type);                                   		/* 返回最近一次ADC1规则组的转换结果 */
}

/***********************************************************************************
 * @brief 通道ch的转换值取times次,然后平均
 * ex:
 * @par  ch:通道编号
 *       times:获取次数
 * None
 * @par Called functions:
 * None
 * @retval 通道ch的times次转换结果平均值
 **********************************************************************************/
unsigned short Get_Adc_Average(ADC_DEVICE_E ch,unsigned char times)
{
	unsigned int temp_val=0;
	unsigned char t;

	if (ch >= ADC_NUM)
		return 0;

	for(t=0;t<times;t++)
	{
		temp_val+=Get_Adc(ch);
		vTaskDelay(pdMS_TO_TICKS(5));
	}
	return temp_val/times;
}

/***********************************************************************************
 * @brief UART_TX_DMA_STREAM 中断程序
 * ex:
 * @par
 * None
 * @retval
 **********************************************************************************/
void DMA2_Stream0_IRQHandler(void)
{
	if(DMA_GetITStatus(ADCx_DMA[DMA_ADC_MF_MONITOR].dma_type, DMA_IT_TCIF0) != RESET)
	{
		DMA_ClearITPendingBit(ADCx_DMA[DMA_ADC_MF_MONITOR].dma_type, DMA_IT_TCIF0);//清除传输结束标志
		ADC_Sampling_Data(DMA_ADC_MF_MONITOR);
	}
}

/**************************************************************************************************
 * @brief 
 * ex:
 * @par
 * None
 * @retval
**************************************************************************************************/
void ADCx_SetCallback(ADC_DMA_DEVICE_E index, void (*cb)(int16_t *, uint16_t))
{
   ADCx_DMA[index].callback = cb;
}

/***********************************************************************************
 * @brief 接收字符串
 * ex:
 * @par
 * None
 * @retval
 **********************************************************************************/
static void ADC_Sampling_Data(ADC_DMA_DEVICE_E index)
{
	uint8_t  CT = 0;
	int16_t *pbuf;
	ADCx_DMA_t *p_dma;

	if (index >= DMA_ADC_NUM)
		return;
	
	p_dma = &ADCx_DMA[index];

	CT = DMA_GetCurrentMemoryTarget(p_dma->dma_type);
	if( p_dma->ADC_DMA_par.MCT != CT ){
		if(CT == 0){
			pbuf = p_dma->ADC_DMA_par.AR1;
		}
		else{
			pbuf = p_dma->ADC_DMA_par.AR0;
		}
		p_dma->ADC_DMA_par.addr = SAMPLING_MAX_SIZE;
		p_dma->ADC_DMA_par.MCT = CT;
	}

	if ( DMA_GetCmdStatus(p_dma->dma_type) == DISABLE) { //可能是传输停止或传输错误引起的
		if(CT == 0){
			pbuf = p_dma->ADC_DMA_par.AR0;
			DMA_DoubleBufferModeConfig(p_dma->dma_type,(u32)p_dma->ADC_DMA_par.AR1,DMA_Memory_1);
		}
		else{
			pbuf = p_dma->ADC_DMA_par.AR1;
			DMA_DoubleBufferModeConfig(p_dma->dma_type,(u32)p_dma->ADC_DMA_par.AR1,DMA_Memory_0);
		}
		p_dma->ADC_DMA_par.addr = SAMPLING_MAX_SIZE - p_dma->dma_type->NDTR;    //当前的数据量
		p_dma->ADC_DMA_par.MCT = DMA_GetCurrentMemoryTarget(p_dma->dma_type);
		DMA_ClearFlag(p_dma->dma_type,p_dma->ADC_DMA_IT_ALL);
//			DMA_SetCurrDataCounter(p_dma->dma_type, ARRAY_MAX_SIZE); //重新加载计数器,根据手册使能后会自动重新加载先前的值此步可以省略
		DMA_Cmd(p_dma->dma_type, ENABLE);
	}
	if(p_dma->callback!=NULL){
		//----------装载数据----------//
		p_dma->callback(pbuf,p_dma->ADC_DMA_par.addr);
	}
	p_dma->ADC_DMA_par.addr = 0;
}
/******************* (C) COPYRIGHT 2022 CIQTEK Moon *****END OF FILE****/
